package sdmaker.ast;

import java.util.ArrayList;
import java.util.List;

import sdmaker.parser.SetStateData;
import sdmaker.parser.ParseResult;
import sdmaker.parser.SDMakerGenerator;
import sdmaker.parser.StateData;
import sdmaker.parser.Utils;

import fsa.State;
import fsa.Transition;

public class ASTloop implements AST {
	private List<AST> body;

	
	
	/* ************************ *
	 * ***** CONSTRUCTORS ***** *
	 * ************************ */
	
	ASTloop(List<AST> body){
		this.body= body;
	}

	
	
	/* ************************ *
	 * ******** GETTERS ******* *
	 * ************************ */
	public int size(){
		return body.size();
	}
	
	
	
	/* ************************ *
	 * ******* TESTERS ******** *
	 * ************************ */
	
	public static Boolean leadToLoop(
			StateData n, SetStateData treatedStates, 
			SetStateData forbiddenStates){	
		return (findSimpleLoop(n, treatedStates, forbiddenStates)!=null);
	}
	
	
	
	/* ************************ *
	 * ******** OTHERS ******** *
	 * ************************ */
	
	public static Transition findSimpleLoop(
			StateData n, SetStateData seenStates, 
			SetStateData forbiddenStates){
	Transition leadToLoop= null;

		for(Transition t : n.getSuccesseurs()){
			StateData target= StateData.getStateData(t.getTarget());
			
			if(forbiddenStates.contains(target)==false&&
					seenStates.contains(target)&&
					n.isAlreadyParsedTransition(t)==false){
				leadToLoop=t;
				break;
			}
		}
		
		return leadToLoop;
	}

	public static void parseLoop(
			SDMakerGenerator generator, StateData n, 
			SetStateData seenStates, SetStateData forbiddenStates){
		
		List<ParseResult> body= new ArrayList<ParseResult>();
		ParseResult lastParseResult= generator.getLastParsed();
		ParseResult tmp= lastParseResult;
		Transition leadingToLoop=findSimpleLoop(n, seenStates, forbiddenStates);
		StateData target= StateData.getStateData(leadingToLoop.getTarget());
		
		do{
			
			body.add(tmp);
			generator.remove(tmp);
			
			if(target.equals(tmp.getStartingState().getNextStateData(0))){
				break;
			}

			tmp= tmp.getPreviousParseResult();
		}while(true);

		//on as recupere les elements dans l'ordre inverse.
		body= Utils.reverse(body);

		ParseResult first= body.get(0);
		ParseResult last= Utils.getLast(body);
		StateData startingState= first.getStartingState();
		StateData finishingState= last.getFinishingState();
		AST loop= new ASTloop(Utils.toListAST(body));

		seenStates.add(n);
		n.addParsedTransition(leadingToLoop);

		generator.add(new ParseResult(
				startingState, 
				finishingState, 
				loop, 
				lastParseResult.getLastTransition(),
				generator.getLastParsed(), null,
				seenStates));
	}
	
	public String toString(){
		String result="";

		result+="Loop {";
		for(AST ast: body){
			result+="\n\t"+ast;
		}
		result+="\n}";

		return result;
	}
}
